package com.example.controller;


import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.example.mapper.Logging;
import com.example.pojo.*;
import com.example.service.CityService;
import com.example.service.RoadService;
import jakarta.annotation.PostConstruct;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.time.Duration;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

@Slf4j
@RestController
public class Getss {

    @Autowired
    private RoadService roadService;
    @Autowired
    private CityService cityService;

    //路网信息都在list中
    private List<Road> list;
    //城市信息表
    public List<City> cities;
    public static String url;
    private Map<String, List<Road>> travelMap;
    List<ResultData> resultList = new ArrayList<>();


    @PostConstruct
    public void init() {
        //初始化所有路网信息
        list = roadService.list();
        cities = cityService.getCities();
        //将数据封装到Map中便于查找
        travelMapInit();
        // log.info("map构造查看{}", travelMap);
        //log.info("比较：{}", LocalDateTime.parse("2024-01-05T16:35").isBefore(LocalDateTime.parse("2024-01-05T18:50")));


        //根据起止点获取bus花费时间
        //getBusTime();
    }

    @GetMapping("/cities")
    public Result getCities() {
        cities = cityService.getCities();
        if (cities.get(0).getLat() == null) {
            getCityInfoFromBaiDu();
        }

        //getCityInfoFromBaiDu();
        log.info("查询城市:{}", cities);
        return Result.success(cities);
    }

    /**
     * 像百度发请求获取经纬度
     */
    public void getCityInfoFromBaiDu() {
        for (City i : cities) {
            url = "https://api.map.baidu.com/geocoding/v3/?address=" + i.getName() + "&output=json&ak=Gc62l1omuSwy4WO62gr0vkAtU4QQyzFZ&callback=showLocation";
            try {
                // 创建URL对象
                URL obj = new URL(url);
                // 打开连接
                HttpURLConnection con = (HttpURLConnection) obj.openConnection();
                // 设置请求方法为GET
                con.setRequestMethod("GET");
                // 获取响应状态码
                int responseCode = con.getResponseCode();
                System.out.println("Response Code: " + responseCode);
                // 读取响应内容
                BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream()));
                String inputLine;
                StringBuilder response = new StringBuilder();
                while ((inputLine = in.readLine()) != null) {
                    response.append(inputLine);
                }
                in.close();
                // 将字符串解析为 JSON 对象
                JSONObject jsonObject = JSON.parseObject(response.toString().split("\\(")[1].split("\\)")[0]);

                JSONObject locationObj = jsonObject.getJSONObject("result").getJSONObject("location");

                // 从 JSON 对象中提取 lng 和 lat 的值
                String lng = locationObj.getString("lng");
                String lat = locationObj.getString("lat");

                // 打印提取的值
                System.out.println("lng: " + lng);
                System.out.println("lat: " + lat);

                //存入数据库
                cityService.save(new City(i.getId(), i.getName(), lng, lat));

            } catch (IOException e) {
                e.printStackTrace();
            }

        }


    }

    /**
     * 根据传递的城市名查找相应的路网信息
     *
     * @param city
     * @return
     */
    @PostMapping("/roads")
    public Result getroads(@RequestBody City city) {
        log.info("cityinfo,{}", city);
        List<Road> roads = new ArrayList<>();
        //System.out.println(list);
        for (Road s : list) {
            if (s.getDeptCity().equals(city.getName())) {
                roads.add(s);
            }
        }
        //System.out.println(cities);
        log.info("查询出发点为{}的路网信息", city.getName());

        return Result.success(roads);
    }

    /**
     * 获取最小花费
     */


    /**
     * 根据起止点获取驾车时间（bus没有时间，根据起止点计算时间）
     */
    public void getBusTime() {
        List<FromTo> roadlist = new ArrayList<>();
        for (int i = 0; i < cities.size(); i++) {
            for (int j = 0; j < cities.size(); j++) {
                if (i == j) continue;
                roadlist.add(new FromTo(cities.get(i).getName(), cities.get(i).getLat().substring(0, 6), cities.get(i).getLng().substring(0, 6),
                        cities.get(j).getName(), cities.get(j).getLat().substring(0, 6), cities.get(j).getLng().substring(0, 6)));
            }
        }


        for (FromTo i : roadlist) {
            url = "https://api.map.baidu.com/directionlite/v1/driving?origin=" + i.getStartLat() + "," + i.getStartLng()
                    + "&destination=" + i.getEndLat() + "," + i.getEndLng() +
                    "&ak=Gc62l1omuSwy4WO62gr0vkAtU4QQyzFZ&callback=showLocation";
            try {
                // 创建URL对象
                URL obj = new URL(url);
                // 打开连接
                HttpURLConnection con = (HttpURLConnection) obj.openConnection();
                // 设置请求方法为GET
                con.setRequestMethod("GET");
                // 获取响应状态码
                int responseCode = con.getResponseCode();
                System.out.println("Response Code: " + responseCode);
                // 读取响应内容
                BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream()));
                String inputLine;
                StringBuilder response = new StringBuilder();
                while ((inputLine = in.readLine()) != null) {
                    response.append(inputLine);
                }
                in.close();
                // 将字符串解析为 JSON 对象
                int time = Integer.parseInt(response.toString().split(",")[8].split(":")[1]);
                //存入文件
                // 存入文件
                writeToLogFile(i.getStartName(), i.getEndName(), time);
            } catch (IOException e) {
                // e.printStackTrace();
            }

        }
    }

    private void writeToLogFile(String start, String end, int time) {
        // 定义文件名，根据需要修改
        String fileName = "bus_times.txt";

        try (BufferedWriter writer = new BufferedWriter(new FileWriter(fileName, true))) {
            // 在文件末尾追加数据
            writer.write(start + " " + end + " " + time);
            writer.newLine(); // 换行
        } catch (IOException e) {
            // 处理文件写入异常
        }
    }


    /**
     * 三种算法得到路径规划
     *
     * @return
     */
    @PostMapping("/selection")
    public Result get1(@RequestBody SelectionRequest selection) {
        this.resultList = new ArrayList<>();
        log.info("请求为：{}", selection);
        //获取途径城市信息ids
        List<Integer> ids = new ArrayList<>();
        for (int i = 2; i < selection.getPathway().size(); i++) {
            ids.add(selection.getPathway().get(i).getId());
        }
        //前两个为起止地址，后面的是途径城市
        City from = selection.getPathway().get(0);
        City to = selection.getPathway().get(1);
        //dfs遍历所有路径
        int[] nums = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
        boolean[] visited = new boolean[nums.length + 2];
        List<Integer> path = new ArrayList<>();
        List<List<Integer>> result = new ArrayList<>();
        dfs(nums, visited, path, result, 0, from.getId(), to.getId(), ids);

        if (selection.getChoice() == 1) {
            log.info("最少花费");
            for (List<Integer> r : result) {
                LocalDateTime temp = LocalDateTime.of(2034, 1, 1, 0, 0, 0);
                List<Road> roadInfo = new ArrayList<>();//记录每条路的所有路径信息
                LocalDateTime temp2 = selection.getStart().plusHours(8);//用于记录每次开始的时间
                boolean flag2 = true;//判断当前路径是否走完
                Double cost = 0.0;//总的花费
                Double tcost = 0.0;//临时变量
                for (int i = 0; i < r.size() - 1; i++) {
                    if (i > 0) {
                        temp2 = temp;//用于记录每次开始的时间
                    }
                    Road roadTemp = new Road();
                    boolean flag = true;//判断是否为两城市之间的第一次比较
                    List<Road> roadFromTravelMap = getRoadFromTravelMap(getNameById(r.get(i)), getNameById(r.get(i + 1)));
                    for (Road road : roadFromTravelMap) {
                        if (((flag == true) || tcost > road.getPrice()) && (road.getStart().isAfter(temp2))) {
                            tcost = road.getPrice();
                            temp = road.getEnd();
                            roadTemp = road;
                            flag = false;
                        }
                    }
                    if (roadFromTravelMap.isEmpty() || (roadTemp.getStart() == null)) {
                        flag2 = false;
                        break;
                    }
                    cost += tcost;
                    roadInfo.add(roadTemp);
                }
                if (flag2 == true) {
                    resultList.add(new ResultData(roadInfo, temp, cost));
                }
            }
            // 根据temp排序得到最早时间
            Collections.sort(resultList, sort2);
            // 输出排序后的结果
            System.out.println(this.resultList.get(0));

        } else if (selection.getChoice() == 2) {
            log.info("最少时间");
            for (List<Integer> r : result) {
                LocalDateTime temp = LocalDateTime.of(2034, 1, 1, 0, 0, 0);
                List<Road> roadInfo = new ArrayList<>();//记录每条路的所有路径信息
                LocalDateTime temp2 = selection.getStart().plusHours(8);//用于记录每次开始的时间
                boolean flag2 = true;//判断当前路径是否走完
                for (int i = 0; i < r.size() - 1; i++) {
                    if (i > 0) {
                        temp2 = temp;//用于记录每次开始的时间
                    }
                    Road roadTemp = new Road();
                    boolean flag = true;//判断是否为两城市之间的第一次比较
                    List<Road> roadFromTravelMap = getRoadFromTravelMap(getNameById(r.get(i)), getNameById(r.get(i + 1)));
                    for (Road road : roadFromTravelMap) {
                        if (((flag == true) || road.getEnd().isBefore(temp)) && (road.getStart().isAfter(temp2))) {
                            temp = road.getEnd();
                            roadTemp = road;
                            flag = false;
                        }
                    }
                    if (roadFromTravelMap.isEmpty() || (roadTemp.getStart() == null)) {
                        flag2 = false;
                        break;
                    }
                    roadInfo.add(roadTemp);
                }
                if (flag2 == true) {
                    resultList.add(new ResultData(roadInfo, temp, 0.0));
                }
            }
            // 根据temp排序得到最早时间
            Collections.sort(resultList);
            // 输出排序后的结果
            System.out.println(this.resultList.get(0));

        } else if (selection.getChoice() == 3) {
            log.info("限时最少费用");
            for (List<Integer> r : result) {
                LocalDateTime temp = LocalDateTime.of(2034, 1, 1, 0, 0, 0);
                List<Road> roadInfo = new ArrayList<>();//记录每条路的所有路径信息
                LocalDateTime temp2 = selection.getStart().plusHours(8);//用于记录每次开始的时间
                boolean flag2 = true;//判断当前路径是否走完
                Double cost = 0.0;//总的花费
                Double tcost = 0.0;//临时变量
                for (int i = 0; i < r.size() - 1; i++) {
                    if (i > 0) {
                        temp2 = temp;//用于记录每次开始的时间
                    }
                    Road roadTemp = new Road();
                    boolean flag = true;//判断是否为两城市之间的第一次比较
                    List<Road> roadFromTravelMap = getRoadFromTravelMap(getNameById(r.get(i)), getNameById(r.get(i + 1)));
                    for (Road road : roadFromTravelMap) {
                        if (((flag == true) || tcost > road.getPrice()) && (road.getStart().isAfter(temp2))) {
                            tcost = road.getPrice();
                            temp = road.getEnd();
                            roadTemp = road;
                            flag = false;
                        }
                    }
                    if (roadFromTravelMap.isEmpty() || (roadTemp.getStart() == null)) {
                        flag2 = false;
                        break;
                    }
                    cost += tcost;
                    roadInfo.add(roadTemp);
                }
                if (flag2 == true) {
                    if(temp.isBefore(selection.getStart().plusDays(selection.getLimit()+1))){
                        resultList.add(new ResultData(roadInfo, temp, cost));
                    }
                }
            }
            // 根据temp排序得到最早时间
            Collections.sort(resultList, sort2);
            // 输出排序后的结果
            System.out.println(this.resultList.get(0));
        }

        return Result.success(this.resultList.get(0));
    }

    // 定义排序规则
    public static Comparator<ResultData> sort2 = new Comparator<ResultData>() {
        @Override
        public int compare(ResultData o1, ResultData o2) {
            return o1.getCost().compareTo(o2.getCost());
        }
    };


    /**
     * dfs获取所有要求的路径
     *
     * @param nums
     * @param visited
     * @param path
     * @param result
     * @param count
     * @param from
     * @param to
     * @param ids
     */
    private static void dfs(int[] nums, boolean[] visited, List<Integer> path,
                            List<List<Integer>> result, Integer count, Integer from,
                            Integer to, List<Integer> ids) {
        if (path.size() > 0 && path.get(0) != from) return;
        if (count == ids.size() && path.size() > 0 && path.get(0) == from && path.get(path.size() - 1) == to) {
            result.add(new ArrayList<>(path));
            return;
        }

        for (int i = 1; i <= nums.length; i++) {
            if (!visited[i]) {
                path.add(nums[i - 1]);
                visited[i] = true;
                if (ids.contains(i)) {
                    dfs(nums, visited, path, result, count + 1, from, to, ids);
                } else dfs(nums, visited, path, result, count, from, to, ids);
                path.remove(path.size() - 1);
                visited[i] = false;

            }
        }
    }

    /**
     * 日记记录
     */
    @PostMapping("/Logging")
    public static Result LoggingInfo(@RequestParam("Info") String info) throws IOException {
        log.info("添加信息,{}",info);
        Logging.addLogging(info);
        return Result.success();
    }

    /**
     * 日志删除
     */
    @DeleteMapping("/Logging")
    public static Result LoggingDelete() throws IOException {
        log.info("清空日志");
        Logging.deleteLogging();
        return Result.success();
    }

    /**
     * 日志查询
     */
    @GetMapping ("/Logging")
    public static Result LoggingGet() throws IOException {
        log.info("日志查询");
        List<String> logging = Logging.getLogging();
        return Result.success(logging);
    }

    /**
     * 通过id查询城市名
     */
    public String getNameById(Integer id) {
        for (int i = 0; i < this.cities.size(); i++) {
            if (this.cities.get(i).getId() == id) return this.cities.get(i).getName();
        }
        return null;
    }

    /**
     * 根据城市名获取id
     *
     * @param name
     * @return
     */
    public Integer getIdByName(String name) {
        for (int i = 0; i < this.cities.size(); i++) {
            if (this.cities.get(i).getName().equals(name)) return this.cities.get(i).getId();
        }
        return null;
    }


    public void travelMapInit() {
        travelMap = new HashMap<>();
        for (Road road : list) {
            String key = road.getDeptCity() + "-" + road.getArrCity();
            List<Road> roadFromTravelMapByKey = getRoadFromTravelMapByKey(key);
            if (roadFromTravelMapByKey != null)
                roadFromTravelMapByKey.add(road);
            else roadFromTravelMapByKey = new ArrayList<>();
            travelMap.put(key, roadFromTravelMapByKey);
        }
    }



    /**
     * 两中获取从起点到终点的方式
     *
     * @param deptCity
     * @param arrCity
     * @return
     */

    public List<Road> getRoadFromTravelMap(String deptCity, String arrCity) {
        String key = deptCity + "-" + arrCity;
        return travelMap.get(key);
    }

    public List<Road> getRoadFromTravelMapByKey(String key) {
        return travelMap.get(key);
    }




}
